using System.Linq;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Project1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    /// 

    public class Game1 : Microsoft.Xna.Framework.Game
    {


        GraphicsDeviceManager _graphics;
        Texture2D _backgroundTexture;
        SpriteFont _font;
        PickupFactory _pickupFactory = new PickupFactory();

        private string[] levelnumber = {"level1","level2", "level3"};

        public Game1()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            cash = 0;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            var levelDescriptor = Content.Load<LevelDescriptor.Level>("level3");
            foreach(var levelObj in levelDescriptor.Objects)
            {
                // C# has unfortunate scoping rules regarding levelObj.
                var objPos = levelObj.Position;

                switch(levelObj.ObjectType)
                {
                    case "block":
                        Components.Add(new Block(this, objPos));
                        break;

                    case "miniblock":
                        Components.Add(new MiniBlock(this, objPos));
                        break;

                    case "portal":
                        Components.Add(new Portal(this, objPos));
                        break;

                    case "player":
                        Components.Add(new Player(this, objPos));
                        break;
                    case "gkey":
                        Components.Add(new gkey(this, objPos));
                        break;
                    case "cop":
                        Components.Add(new cop(this, objPos));
                        break;
                    case "phone":
                        _pickupFactory.AddPickup(() =>
                        {
                                var p = new PhonePickup(this, objPos);
                                Components.Add(p);
                                return p;
                            },
                            levelObj.RespawnInterval);
                        break;

                    case "bomb":
                        _pickupFactory.AddPickup(() =>
                            {
                                var p = new BombPickup(this, objPos);
                                Components.Add(p);
                                return p;
                            },
                            levelObj.RespawnInterval);
                        break;
                }
            }

            PlayerStart = Components.OfType<Player>().First().Position;
            base.Initialize();
        }

        public SpriteBatch SpriteBatch { get; private set; }

        public int ScreenWidth { 
            get { return GraphicsDevice.PresentationParameters.BackBufferWidth; } 
        }
        public int ScreenHeight {
            get { return GraphicsDevice.PresentationParameters.BackBufferHeight; }
        }

        public Vector2 PlayerStart { get; private set; }

        public int cash { get; set; }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            SpriteBatch = new SpriteBatch(GraphicsDevice);
            // TODO: use this.Content to load your game content here
            _font = Content.Load<SpriteFont>(@"ScoreFont");
            _backgroundTexture = Content.Load<Texture2D>("evanston");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent() { }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                this.Exit();
            }

            // Find the player object
            Player pl = Components.OfType<Player>().First();

            List<BoundedObject> deadObjects = new List<BoundedObject>();
            foreach(var c in Components.OfType<BoundedObject>())
            {
                if (c != pl && c.BoundingRect.Intersects(pl.BoundingRect))
                {
                    if (c.OnPlayerCollide(pl))
                    {
                        deadObjects.Add(c);
                    }
                }
            }
            deadObjects.ForEach(x => Components.Remove(x));

            _pickupFactory.Update(gameTime);

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);
            string scoreString = "$" + cash.ToString();
            // half the screen and a little to the left
            Vector2 textPos = new Vector2(GraphicsDevice.Viewport.Bounds.Width / 2 - 25, 10.0f);

            SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            DrawBackground();
            SpriteBatch.DrawString(_font, scoreString, textPos, Color.Black);
            
            SpriteBatch.End();

            SpriteBatch.Begin();
            base.Draw(gameTime);
            SpriteBatch.End();
        }
        private void DrawBackground()
        {
            Rectangle screenRectangle = new Rectangle(0, 0, ScreenWidth, ScreenHeight);
            SpriteBatch.Draw(_backgroundTexture, screenRectangle, Color.White);
        }
    }
}
